//编写一个 h()
const h = (tag, props, children) => {
//vnode -> javascript -> {}
    return {
        tag,
        props,
        children
    }
}


const mount = (vnode, container) => {
    //vnode -> element  挂载转为真正的element元素

    //1.创建出真是的原生，并且在vnode上保留el
    //给vnode添加一个属性el
    const el = vnode.el = document.createElement(vnode.tag);

    //2.处理 props
    if(vnode.props) {
        for (const key in vnode.props) {
            // console.log(vnode.props[key])
            const value = vnode.props[key];
            if(key.startsWith("on")) {  //传来的是点击事件处理
                el.addEventListener(key.slice(2).toLowerCase(), value) //例如：("click", function(){})
            }else {
                el.setAttribute(key, value)
            }
        }
    }

    //3.处理 children
    if(vnode.children) {
        // console.log(typeof vnode.children)
        if(typeof vnode.children === "string") {
            el.textContent = vnode.children;
        }else {
            //不是字符串的话就 循环 继续递归
            vnode.children.forEach(item => {
                mount(item, el)
            });
        }
    }

    //4.挂载
    container.appendChild(el);
}


const patch = (n1, n2) => {
    if(n1.tag !== n2.tag) {//节点（tag）不相同
        const n1Elparent = n1.el.parentElement;
        n1Elparent.removeChild(n1.el);
        mount(n2, n1Elparent)
    }else {
        //1.处理相同tag   取出element,并且在n2中进行保存
        // console.log(n1.el, n2.el)
        const el = n2.el = n1.el;
        
        //2.处理props
        const oldProps = n1.props || {};
        const newProps = n2.props ||{};
        // console.log(oldProps, newProps)
        //2.1 获取所有的newProps添加到el
        for(const key in newProps) {
            const newVal = newProps[key];
            const oldVal = oldProps[key];
            if(newVal !== oldVal) {
                if(key.startsWith("on")) {
                    el.addEventListener(key.slice(2).toLowerCase(), newVal)
                }else {
                    el.setAttribute(key, newVal)
                }
            }
        }
        //2.2 删除旧的props
        for(const key in oldProps) {
            // if(!(key in newProps)) {
            //     if(key.startsWith("on")) {
            //         el.removeEventListener(key.slice(2).toLowerCase(), oldProps[key])
            //     }else {
            //         el.removeAttribute(key)
            //     }
            // }
            if(key.startsWith("on")) {
                el.removeEventListener(key.slice(2).toLowerCase(), oldProps[key]);
            }
            if(!(key in newProps)) {
                el.removeAttribute(key);
            }
        }
        // console.log(n1.el, n2.el)

        //3.处理 children
        const oldChildren = n1.children || [];
        const newChildren = n2.children || [];
        
        if(typeof newChildren === "string") { //情况一：newchildren本事是一个string
            //边界判断 ->（edge case）
            if(typeof oldChildren === "string") {
                if(newChildren !== oldChildren) {
                    el.textContent = newChildren;
                }
            }else {
                el.innerHTML = newChildren;
            }
        }else { //情况二：newchildren是一个数组
            //2.1 
            if(typeof oldChildren === "string") {
                el.innerHTML = "";
                newChildren.forEach(v => {
                    mount(v, el)
                })
            }else {
                //2.2 两个都是数组 
                // oldChildren: [v1, v2, v3]
                // newChildren: [v1, v5, v6, v7, v9]
                
                //1.相同节点进行patch操作
                const commonlength = Math.min(oldChildren.length, newChildren.length);
                // console.log(commonlength)
                for(let i = 0; i < commonlength; i++) {
                    patch(oldChildren[i], newChildren[i])
                }

                //2.newChildren.length > oldChildren.length
                if(newChildren.length > oldChildren.length) {
                    newChildren.slice(oldChildren.length).forEach(item => {
                        mount(item, el);
                    })
                }

                //3.newChildren.length < oldChildren.length
                if(newChildren.length < oldChildren.length) {
                    console.log( oldChildren)
                    oldChildren.slice(newChildren.length).forEach(item => {
                        el.removeChild(item.el)
                    })
                    console.log( oldChildren)
                }
            }

        }
    }
}